<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>连连看</title>
  </head>
  <!-- 新增自动死局判断,死局后将打乱期棋盘
  新增开始按钮-->
  <!-- 接下来更新 时间条,难度选择,通关判断 -->
  <!-- 未来更新,连击判断,分数系统 -->
  <!-- <body body oncontextmenu=self.event.returnValue=false onselectstart="return false"></body> -->
  <style type="text/css">
    * {
      margin: 0;
      padding: 0;
    }
    body {
      background-color: bisque;
    }

    #container {
      width: 600px;
      height: 600px;
      margin: 0.3rem auto;
      position: relative;
      visibility: hidden;
    }
    #draw {
      position: relative;
    }
    .img {
      width: 60px;
      height: 60px;
      position: absolute;
    }
    #start {
      width: 100%;
      visibility: visible;
    }
    #play {
      width: 20%;
      height: 50px;
      margin: 2rem auto;
      font-weight: bold;
      background-color: crimson;
      line-height: 50px;
      box-shadow: 1px 1px 3px 3px brown;
      text-align: center;
      font-size: 1.7rem;
      color: white;
      transition: all 0.2s;
    }

    #play:hover {
      background-color: red;
      color: yellow;
      width: 22%;
      height: 55px;
      font-size: 2rem;
      cursor: pointer;
    }
  </style>

  <body>
    <div id="start">
      <p id="play">开始游戏</p>
    </div>
    <div id="container">
      <canvas id="draw" width="600px" height="600px"> </canvas>
    </div>
    <script>
      //定义
      var yes = "visible";
      var no = "hidden";
      //开始界面
      var start = document.getElementById("start");
      var play = document.getElementById("play");
      var container = document.getElementById("container");
      play.onclick = function () {
        start.remove();
        container.style.visibility = yes;
      };
      //开始部分

      var draw = document.getElementById("draw");
      var tool = draw.getContext("2d");
      //开始部分设置
      var boxSize = 720;
      container.style.width = boxSize + "px";
      container.style.height = boxSize + "px";
      draw.setAttribute("width", boxSize);
      draw.setAttribute("height", boxSize);
      var n_boxSize = boxSize - 120;
      //记录拐点坐标
      var t3 = 0;
      //创建图案
      var arr = lists((n_boxSize / 60) ** 2);
      var a = 0;
      createImg();
      //创建图案
      function createImg() {
        a = 0;
        for (let i = 0; i < boxSize / 60; i++) {
          for (let j = 0; j < boxSize / 60; j++) {
            //在最外围创建空的一圈方块用于匹配
            if (
              i == 0 ||
              i == boxSize / 60 - 1 ||
              j == 0 ||
              j == boxSize / 60 - 1 ||
              a == arr.length
            ) {
              var img = document.createElement("img");
              img.className = "img";
              img.style.left = 60 * j + "px";
              img.style.top = 60 * i + "px";
              img.style.visibility = no;
              container.appendChild(img);
            } else {
              var img = document.createElement("img");
              img.className = "img";
              img.src = "../images/img_" + arr[a] + ".png";
              img.style.left = 60 * j + "px";
              img.style.top = 60 * i + "px";
              img.alt = arr[a++];
              container.appendChild(img);
            }
          }
        }
      }
      //对象
      function positions() {
        this.setpositions = function (obj) {
          this.x = Math.floor(Number(obj.offsetLeft) / 60);
          this.y = Math.floor(Number(obj.offsetTop) / 60);
          this.rx = obj.offsetLeft + obj.width / 2;
          this.ry = obj.offsetTop + obj.height / 2;
        };
      }
      function positionTemp(x, y) {
        this.x = Number(x);
        this.y = Number(y);
        this.rx = x * 60 + 30;
        this.ry = y * 60 + 30;
      }
      var p1 = new positions();
      var p2 = new positions();
      var arr_temp = new Array();
      var arr_id = new Array();
      var imgs = 0;
      var arr_box = 0;
      //计数
      var count = 0;
      setImg();
      function setImg() {
        imgs = document.getElementsByClassName("img");
        arr_box = new Array();
        a = 0;
        for (let i = 0; i < imgs.length / (boxSize / 60); i++) {
          arr_box[i] = new Array();
          for (let j = 0; j < imgs.length / (boxSize / 60); j++) {
            arr_box[i][j] = imgs[a++];
          }
        }
        for (let i = 0; i < arr_box.length; i++) {
          for (let j = 0; j < arr_box[i].length; j++) {
            arr_box[i][j].onclick = function (e) {
              arr_temp.push(e.target);
              console.log(arr_temp.length);
              if (arr_temp.length == 2) {
                e.target.style.opacity = 0.8;
                //判断是否能消除
                if (whether()) {
                  draws();
                  deletes(true);
                  count += 2;
                  //判断是否消除了所有方块
                  if (count == (n_boxSize / 60) ** 2) {
                    alert("胜利");
                  } else {
                    //判断死局
                    if (!checks()) {
                      alert("已成死局,系统将重新打乱");
                      arr = lists(death());
                      createImg();
                      setImg();
                    } else {
                      deletes(false);
                    }
                  }
                } else {
                  deletes(false);
                }
              } else {
                e.target.style.opacity = 0.8;
              }
              //   p1.setpositions(e.target);
            };
          }
        }
      }
      //创建存储坐标的数组
      var arr_draws = new Array();
      for (let i = 0; i < 4; i++) {
        arr_draws[i] = new Array();
        for (let j = 0; j < 2; j++) {
          arr_draws[i][j] = 0;
        }
      }
      //记录绘画坐标
      var r1 = 0;
      var r2 = 0;
      //绘制线条
      function draws() {
        tool.beginPath();
        tool.lineCap = "round";
        tool.lineJoin = "round";
        tool.lineWidth = "3";
        tool.strokeStyle = "red";
        tool.moveTo(arr_draws[0][0], arr_draws[0][1]);
        for (let i = 1; i < arr_draws.length; i++) {
          for (let j = 0; j < 2; ) {
            //等于0的时候说明没有坐标,直接结束循环
            if (arr_draws[i][j] != 0) {
              tool.lineTo(arr_draws[i][j++], arr_draws[i][j]);
            } else {
              break;
            }
          }
        }
        //   tool.closePath();
        tool.stroke();
        // 0.4秒后消除线条;
        setTimeout(function () {
          //清除两个点之间所有画线
          tool.clearRect(0, 0, boxSize, boxSize);
        }, 400);
      }
      function drawsSave(p) {
        arr_draws[r1][r2++] = p.rx;
        arr_draws[r1++][r2] = p.ry;
        r2 = 0;
      }
      function deletes(b) {
        if (b) {
          arr_temp[0].style.visibility = no;
          arr_temp[1].style.visibility = no;
        } else {
          arr_temp[0].style.opacity = 1;
          arr_temp[1].style.opacity = 1;
        }
        r1 = 0;
        r2 = 0;
        //将数组归0
        for (let i = 0; i < 4; i++) {
          for (let j = 0; j < 2; j++) {
            arr_draws[i][j] = 0;
          }
        }
        arr_temp.splice(0);
      }
      function whether() {
        p1.setpositions(arr_temp[0]);
        p2.setpositions(arr_temp[1]);
        //写入第一个坐标
        drawsSave(p1);
        //判断图案相同
        if (arr_temp[0].alt != arr_temp[1].alt) {
          return false;
        }
        //判断是否同一方块
        if (p1.x == p2.x && p1.y == p2.y) {
          return false;
        }
        //判断是否连接
        if (!(zeros(p1, p2) || ones(p1, p2) || twos(p1, p2))) {
          return false;
        }
        //后写入拐点坐标,因为如果有两个拐点,第一个后第二个拐点坐标位置会反过来
        if (t3 != 0) {
          drawsSave(t3);
        }
        t3 = 0;
        //写入最后一个坐标
        drawsSave(p2);
        return true;
      }
      //判断方法
      function zeros(c1, c2) {
        //判断是否是同行或列位置方块
        if (c1.x == c2.x || c1.y == c2.y) {
          let min = 0;
          let max = 0;
          if (c1.y == c2.y) {
            max = c1.x > c2.x ? c1.x : c2.x;
            min = c1.x > c2.x ? c2.x : c1.x;
            for (let i = min + 1; i < max; i++) {
              if (arr_box[c1.y][i].style.visibility != no) {
                return false;
              }
            }

            return true;
          }
          if (c1.x == c2.x) {
            max = c1.y > c2.y ? c1.y : c2.y;
            min = c1.y > c2.y ? c2.y : c1.y;
            for (let i = min + 1; i < max; i++) {
              if (arr_box[i][c1.x].style.visibility != no) {
                return false;
              }
            }

            return true;
          }
          return false;
        }
      }
      function ones(c1, c2) {
        if (arr_box[c1.y][c2.x].style.visibility == no) {
          let t1 = new positionTemp(c2.x, c1.y);
          if (zeros(c1, t1)) {
            if (zeros(t1, c2)) {
              t3 = t1;
              return true;
            }
          }
        }
        if (arr_box[c2.y][c1.x].style.visibility == no) {
          let t2 = new positionTemp(c1.x, c2.y);
          if (zeros(c2, t2)) {
            if (zeros(t2, c1)) {
              t3 = t2;
              return true;
            }
          }
        }
        return false;
      }
      function twos(c1, c2) {
        let i = 1;
        while (true) {
          if (c1.y - i >= 0) {
            let temp = new positionTemp(c1.x, c1.y - i);
            if (arr_box[temp.y][temp.x].style.visibility == no) {
              //因为先执行了一个拐点判断,所有会先记录第二个的拐点坐标
              if (ones(temp, c2)) {
                drawsSave(temp);
                return true;
              }
            } else {
              break;
            }
          } else {
            break;
          }
          i++;
        }
        i = 1;
        while (true) {
          if (c1.y + i < arr_box.length) {
            let temp = new positionTemp(c1.x, c1.y + i);
            if (arr_box[temp.y][temp.x].style.visibility == no) {
              if (ones(temp, c2)) {
                drawsSave(temp);
                return true;
              }
            } else {
              break;
            }
          } else {
            break;
          }
          i++;
        }
        i = 1;
        while (true) {
          if (c1.x - i >= 0) {
            let temp = new positionTemp(c1.x - i, c1.y);
            if (arr_box[temp.y][temp.x].style.visibility == no) {
              if (ones(temp, c2)) {
                drawsSave(temp);
                return true;
              }
            } else {
              break;
            }
          } else {
            break;
          }
          i++;
        }
        i = 1;
        while (true) {
          if (c1.x + i < arr_box.length) {
            let temp = new positionTemp(c1.x + i, c1.y);
            if (arr_box[temp.y][temp.x].style.visibility == no) {
              if (ones(temp, c2)) {
                drawsSave(temp);
                return true;
              }
            } else {
              break;
            }
          } else {
            break;
          }
          i++;
        }
        return false;
      }
      //   随机功能;
      // (n_boxSize / 60) ** 2
      function lists(num) {
        let r_arr1 = new Array();
        //平方
        for (let i = 0; i < num / 2; i++) {
          if (i < 20) {
            r_arr1[i] = i;
          } else {
            r_arr1[i] = Math.floor(Math.random() * 20);
          }
        }
        let r_arr2 = r_arr1.slice(0, r_arr1.length);
        let arr = [].concat(r_arr1, r_arr2);
        for (let i = 0; i < arr.length; i++) {
          let r = Math.floor(Math.random() * arr.length);
          let temp = arr[i];
          arr[i] = arr[r];
          arr[r] = temp;
        }
        return arr;
      }
      //查询是否还有可以消除的方块
      function checks() {
        for (let i = 1; i < arr_box.length - 1; i++) {
          for (let j = 1; j < arr_box[0].length - 1; j++) {
            for (let k = 1; k < arr_box.length - 1; k++) {
              for (let t = 1; t < arr_box[0].length - 1; t++) {
                if (
                  arr_box[i][j].style.visibility == no ||
                  arr_box[k][t].style.visibility == no
                ) {
                  continue;
                }
                //添加坐标点数,与方块
                arr_temp.push(arr_box[i][j]);
                arr_temp.push(arr_box[k][t]);
                if (whether()) {
                  return true;
                } else {
                  deletes(false);
                }
              }
            }
          }
        }

        //返回代表剩下的方块已经死局了
        return false;
      }
      //死局的时候
      function death() {
        let counts = 0;
        for (let i = 0; i < arr_box.length; i++) {
          for (let j = 0; j < arr_box[i].length; j++) {
            if (arr_box[i][j].style.visibility != no) {
              counts++;
            }
            arr_box[i][j].remove();
          }
        }
        return counts;
      }
    </script>
  </body>
</html>
